#include "display.h"
#include "../Simulation.h"

#include "glut_2d.h"
#include "utils.h"

#include <time.h>
#include <math.h>

void display_init(int * argc, char *argv[])
{
    glutInit(argc, argv);
    
    display_names = false;
    funcMaj = NULL;
    
    creerFenetre(800, 800, "GLUT2D");
}

void glut_display()
{
    glClearColor(0.08, 0.08, 0.08, 0);
    glClearDepth(1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    afficher();

    glutSwapBuffers();
}

void glut_idle()
{
    miseAJourSimulation();
    glutPostRedisplay();
}

void displayString (char * string, void * font, float x, float y)
{
  char *c;
  glRasterPos2f(x,y);
  for (c=string; *c != '\0'; c++)
  {
    glutBitmapCharacter(font, *c);
  }
}

void displayDate (time_t t, float x, float y)
{
  char buffer[32];
  struct tm *loctime;
  loctime = localtime (&t);
  strftime (buffer, 32, "Date : %d/%m/%Y %H:%M:%S %Z", loctime);
  displayString(buffer, GLUT_BITMAP_9_BY_15, x, y);
}


void displayParameters ( float x, float y)
{
  char buffer[64];
  sprintf(buffer, "Step : %g s", simul.time_step);
  displayString(buffer, GLUT_BITMAP_9_BY_15, x, y);
  if(simul.speed == 1.0)
    sprintf(buffer, "Speed : real time");
  else if(simul.speed > 1.0)
    sprintf(buffer, "Speed: %g times faster than real time", simul.speed);
  else
    sprintf(buffer, "Speed: %g times slower than real time", 1.0/simul.speed);
  displayString(buffer, GLUT_BITMAP_9_BY_15, x, y+15);
}


void displayScale (float x, float y, float maxl)
{
  int e = (int) trunc(log10(maxl/display_scale));
  afficheLigne(x - pow(10,e)*display_scale, y, x, y);

  char buffer[16];
  sprintf(buffer, "10^%d m", e);
  displayString(buffer, GLUT_BITMAP_8_BY_13, x - 50, y - 10);

}


void processKeyboard(unsigned char key, int x, int y)
{
    switch (key) {
        case '\033': // Esc
        case 'Q':
        case 'q':
            exit(0);
            break;
        case 'P':
        case 'p':
            display_scale *= 1.2;
            break;
        case 'M':
        case 'm':
            display_scale *= 0.8;
            break;
        default:
            break;
    }
}

void processMouse(int button, int state, int x, int y) 
{
	if (state == GLUT_UP )
	{
		if ( button == 3 ) /* GLUT_WHEEL_UP */
		{
			display_scale *= 1.2; /* Zoom in */
		}
		else if( button == 4 ) /* GLUT_WHEEL_DOWN */
		{
			display_scale *= 0.8; /* Zoom out */
		}
	}
}


void glut_reshape(int w, int h)
{
    glViewport(0,0,w,h) ;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity() ;
    glOrtho(0.0f,w,h,0.0f,-1.0f,1.0f);
    glMatrixMode(GL_MODELVIEW) ;
    glLoadIdentity() ;

}

void display_loop()
{
    glutMainLoop();
}

extern void creeDL();

void prepareAffichage()
{
    glutDisplayFunc(glut_display);
    glutKeyboardFunc(processKeyboard);
    glutMouseFunc(processMouse);
    glutIdleFunc(glut_idle);
    glutReshapeFunc(glut_reshape);

    glDepthFunc(GL_LESS);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_DST_COLOR);

    creeDL();

}

void creerFenetre(int largeur, int hauteur, char * nom)
{
    glutInitWindowSize(largeur,hauteur);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutCreateWindow(nom);
    glPointSize(10.0f);
    glLineWidth(10.0f);
    prepareAffichage();
}

void
afficher ()
{
  int w = glutGet(GLUT_WINDOW_WIDTH), h = glutGet(GLUT_WINDOW_HEIGHT);
  int i,x,y;
  for(i = 0; i < simul.particules_num; i++)
  {
    x = w/2 + display_scale*simul.particules[i].position.x;
    y = h/2 - display_scale*simul.particules[i].position.y;
    affichePointDisque(x,y);
    if(display_names)
      displayString (simul.particules[i].designation, GLUT_BITMAP_8_BY_13, x + 10, y + 5);
  }
  time_t t2 = (int) (elapsedTime()*simul.speed) + simul.start_time;
  displayDate(t2,10,h-10);
  displayScale (w - 10, h-10, w/2);
  displayParameters (10,20);
}

void miseAJourSimulation ()
{
  updateSimulation(&simul, elapsedTime());
  if(funcMaj != NULL)
    funcMaj();
}

double elapsedTime(void)
{
    return ((double) glutGet(GLUT_ELAPSED_TIME)) / 1000.0;
}


